#pragma once

#include <app.hpp>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

namespace redfish
{

struct DataRecord{
    std::string Name;
    std::string baseValue;
    std::string hashValue;
    std::string result;
};

inline std::string hexArrayToPrefixedString(const std::vector<unsigned char>& hexArray)
{
    std::ostringstream oss;
    oss << std::hex << std::setfill('0');
    for(unsigned char byte : hexArray)
    {
        oss << std::setw(2) << static_cast<int>(byte);
    }
    return oss.str();
}

inline int getTrustedMetricsInfoFromFile(const std::string& file,DataRecord& record)
{
    std::vector<unsigned char> baseData;
    std::vector<unsigned char> metricsData;

    std::ifstream inputFile(file,std::ios::binary);
    if(!inputFile)
    {
        BMCWEB_LOG_INFO << "Failed to open the file. filePath= " << file;
        return -1;
    }
    const std::streamsize recordSize = 67;
    std::vector<unsigned char> recordData(recordSize);
    if(!inputFile.read(reinterpret_cast<char *>(recordData.data()),recordSize)){
        BMCWEB_LOG_INFO << "Failed to read the record. filePath= " << file;
        inputFile.close();
        return -1;
    }
    inputFile.close();
    baseData.assign(recordData.data()+2,recordData.data()+34);
    record.baseValue = hexArrayToPrefixedString(baseData);
    BMCWEB_LOG_INFO << "baseValue: " << record.baseValue;
    metricsData.assign(recordData.data()+34,recordData.data()+66);
    record.hashValue = hexArrayToPrefixedString(metricsData);
    BMCWEB_LOG_INFO << "hashValue: " << record.hashValue;
    if(recordData[66] == 1)
    {
        record.result = "Pass";
    }
    else
    {
        record.result = "Fail";
    }
    BMCWEB_LOG_INFO << "result: " << record.result;
    return 0;
}


inline void
    getTrustedMetricsInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    int ret = 0;
    DataRecord record;
    nlohmann::json& trustedMetricsInfo = asyncResp->res.jsonValue["TrustedMetrics"];
    trustedMetricsInfo = nlohmann::json::array();
    ret = getTrustedMetricsInfoFromFile("/var/CPUparma",record);
    if(ret==0)
    {
        record.Name = "CPU";
        trustedMetricsInfo.push_back({
                        {"Name", record.Name},
                        {"Base", record.baseValue},
                        {"Value", record.hashValue},
                        {"Status",record.result}});
    }
    ret = getTrustedMetricsInfoFromFile("/var/DIMMparma",record);
    if(ret==0)
    {
        record.Name = "DIMM";
        trustedMetricsInfo.push_back({
                        {"Name", record.Name},
                        {"Base", record.baseValue},
                        {"Value", record.hashValue},
                        {"Status",record.result}});
    }
    ret = getTrustedMetricsInfoFromFile("/var/PCIEparma_Raid",record);
    if(ret==0)
    {
        record.Name = "Raid";
        trustedMetricsInfo.push_back({
                        {"Name", record.Name},
                        {"Base", record.baseValue},
                        {"Value", record.hashValue},
                        {"Status",record.result}});
    }
    ret = getTrustedMetricsInfoFromFile("/var/PCIEparma_NetCard",record);
    if(ret==0)
    {
        record.Name = "NetCard";
        trustedMetricsInfo.push_back({
                        {"Name", record.Name},
                        {"Base", record.baseValue},
                        {"Value", record.hashValue},
                        {"Status",record.result}});
    }
    ret = getTrustedMetricsInfoFromFile("/var/PCIEparma_Nvme",record);
    if(ret==0)
    {
        record.Name = "Nvme";
        trustedMetricsInfo.push_back({
                        {"Name", record.Name},
                        {"Base", record.baseValue},
                        {"Value", record.hashValue},
                        {"Status",record.result}});
    }
    ret = getTrustedMetricsInfoFromFile("/var/PCIEparma_Gpu",record);
    if(ret==0)
    {
        record.Name = "GPU";
        trustedMetricsInfo.push_back({
                        {"Name", record.Name},
                        {"Base", record.baseValue},
                        {"Value", record.hashValue},
                        {"Status",record.result}});
    }
    ret = getTrustedMetricsInfoFromFile("/var/OSparma_Grub",record);
    if(ret==0)
    {
        record.Name = "Grub";
        trustedMetricsInfo.push_back({
                        {"Name", record.Name},
                        {"Base", record.baseValue},
                        {"Value", record.hashValue},
                        {"Status",record.result}});
    }
    ret = getTrustedMetricsInfoFromFile("/var/OSparma_Shim",record);
    if(ret==0)
    {
        record.Name = "Shim";
        trustedMetricsInfo.push_back({
                        {"Name", record.Name},
                        {"Base", record.baseValue},
                        {"Value", record.hashValue},
                        {"Status",record.result}});
    }
    ret = getTrustedMetricsInfoFromFile("/var/OSparma_Static",record);
    if(ret==0)
    {
        record.Name = "APP_Static_NexaGuard";
        trustedMetricsInfo.push_back({
                        {"Name", record.Name},
                        {"Base", record.baseValue},
                        {"Value", record.hashValue},
                        {"Status",record.result}});
    }
    ret = getTrustedMetricsInfoFromFile("/var/OSparma_Dync",record);
    if(ret==0)
    {
        record.Name = "APP_Dync_NexaGuard";
        trustedMetricsInfo.push_back({
                        {"Name", record.Name},
                        {"Base", record.baseValue},
                        {"Value", record.hashValue},
                        {"Status",record.result}});
    }

    ret = getTrustedMetricsInfoFromFile("/var/OSparma_Kernel",record);
    if(ret==0)
    {
        record.Name = "Kernel";
        trustedMetricsInfo.push_back({
                        {"Name", record.Name},
                        {"Base", record.baseValue},
                        {"Value", record.hashValue},
                        {"Status",record.result}});
    }

    ret = getTrustedMetricsInfoFromFile("/var/OSparma_Initrd",record);
    if(ret==0)
    {
        record.Name = "Initrd";
        trustedMetricsInfo.push_back({
                        {"Name", record.Name},
                        {"Base", record.baseValue},
                        {"Value", record.hashValue},
                        {"Status",record.result}});
    }

    ret = getTrustedMetricsInfoFromFile("/var/OSparma_Bios",record);
    if(ret==0)
    {
        record.Name = "Bios_Image";
        trustedMetricsInfo.push_back({
                        {"Name", record.Name},
                        {"Base", record.baseValue},
                        {"Value", record.hashValue},
                        {"Status",record.result}});
    }
    
}

inline void requestRoutesGetTrustedMetricsInfo(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Managers/1/Oem/<str>/trustedMetrics")
        .privileges({{"Login"}})
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& redfishCustomIdStr) {
                if (redfishCustomIdStr != redfishCustomId)
                {
                    messages::resourceNotFound(
                        asyncResp->res, "redfishCustomId", redfishCustomIdStr);
                    return;
                }
                if (!redfish::setUpRedfishRoute(app, req, asyncResp->res))
                {
                    return;
                }

                asyncResp->res.jsonValue["@odata.type"] =
                    "#TrustedMetrics.TrustedMetrics";
                asyncResp->res.jsonValue["@odata.id"] =
                    "/redfish/v1/Managers/1/Oem/" + redfishCustomId +
                    "/trustedMetrics";
                asyncResp->res.jsonValue["Name"] = "TrustedMetrics";
                asyncResp->res.jsonValue["Id"] = "trustedMetrics";
                asyncResp->res.jsonValue["Description"] =
                    "Trusted metrics " + redfishCustomId + " OEM commands";
                getTrustedMetricsInfo(asyncResp);
            });
}

} // namespace redfish